/*
 * @Author: 9ilk 3535851673@qq.com
 * @Date: 2024-11-29 21:36:53
 * @LastEditors: 9ilk 3535851673@qq.com
 * @LastEditTime: 2025-01-03 21:52:57
 * @FilePath: /zhuang/RingBuffer/RingBuffer.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
/*
 * @Author: 9ilk 3535851673@qq.com
 * @Date: 2024-11-29 21:36:53
 * @LastEditors: 9ilk 3535851673@qq.com
 * @LastEditTime: 2024-11-30 20:19:58
 * @FilePath: /zhuang/RingBuffer/RingBuffer.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#pragma once
#include <semaphore.h>
#include "Sem.hpp"
#include <iostream>
#include <pthread.h>
#include "Mutex.hpp"
#include <vector>
using namespace std;
using namespace SemModule;
using namespace LockModule;

namespace RingBufferModule
{
    template <typename T>
    class RingBuffer
    {
    public:
        RingBuffer(int cap)
            : _ring(cap),
              _cap(cap),
              _p_step(0),
              _c_step(0),
              _datasem(0),
              _spacesem(cap) {};
        ~RingBuffer() {};
        void Equeue(const T &in) // 生产者做
        {

            // 必须保证调用接口的安全就得引入信号量
            _spacesem.P(); // 生产者申请空间

            {
                LockGuard lockugard(_p_lock);
                // 选出一个生产者
                _ring[_p_step] = in; // 生产
                _p_step++;
                _p_step %= _cap; // 保证环形特性
                                 // 生产者 不可能生产满
            }
            _datasem.V(); // 生产者释放数据
        }
        void Pop(T *out)
        {
            // 选出一个消费者
            _datasem.P(); // 预订数据
            {
                LockGuard lockugard(_c_lock);
                // 消费
                *out = _ring[_c_step];
                _c_step++;
                _c_step %= _cap; // 保持环形特征
            }
            _spacesem.V(); // 释放空间
        }

    private:
        vector<T> _ring; // 环,临界资源
        int _cap;        // 总容量
        // 表明生产消费者的位置
        int _p_step;
        int _c_step;
        Mutex _p_lock; // 多生产者锁
        Mutex _c_lock; // 多消费者锁
        Sem _datasem;  // 数据信号量
        Sem _spacesem; // 空间信号量
    };

}